package utility;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;

import org.apache.log4j.Logger;

/**
 * Create class named: <b>AppUtilities</b> extending this class for your application
 *
 * @author manh.vu
 */
public class AppUtilities {

	private static final Logger logger = Logger.getLogger(AppUtilities.class);

	private final String HEADER = "manh.vv.htth@gmail.com";

	private File fileOO;
	private static AppUtilities aAU; // Only one instance
	private final File propertyFile; // for storing property file
	private final Properties prop;

	private static final String RESOURCES = "/resources/";
	private static final String CONFIGF = "config";
	public static final String CURRENTPATH = System.getProperty("user.dir");
	public static final String INIFILE = "application.ini"; /* initial or configuration file */
	public static final String LAST_LOCATION = "LastLocation";
	public static final String LAST_FILENAME = "LastFileName";
	public static final String FILEOO = "OOI.ooi";
	public static final String PRODMOD = "ProdMod"; // Production mode: DEV or PROD

	private AppUtilities(File file) throws IOException {
		this.prop = new Properties();
		this.propertyFile = file;
		FileInputStream in = null;

		if(file.exists()) {
			in = new FileInputStream(file);

			if(in.read() > 0) {
				prop.load(in);
			}
		}
		else {
			this.storingPropertiesFile();
		}
	}

	public static AppUtilities createAppUtilities() {
		if(aAU == null) {
			try {
				aAU = new AppUtilities(AppUtilities.getConfigIni());
			}catch (IOException e) {
				logger.error(e.getMessage(), e.getCause());
			}
		}

		return aAU;
	}

	/**
	 * This function will create a file name "OOI.ooi" on time when is invoked. </br>Return true for file already exist. </br>Purpose: use to check only one instance of this
	 * application being executed.
	 *
	 * @return
	 */
	public boolean isFILEOOExisting() {
		// Create file FILEOO
		fileOO = new File(AppUtilities.getConfigFolder(), FILEOO);
		if(fileOO.exists()) {
			return true;
		}

		try {
			fileOO.createNewFile();
			fileOO.deleteOnExit(); // Delete this file when application shutdown
		}catch (IOException e) {
			logger.error(e.getMessage(), e.getCause());
		}
		return false;
	}

	public File getFileOO() {
		isFILEOOExisting();
		return fileOO;
	}

	/**
	 * Use this function to open file in configuration folder <br>
	 * This function will automatically load file having the same name in <br>
	 * the resources folder if it does not exist in configuration folder
	 *
	 * @param fileName
	 * @return
	 */
	public URL openConfigurationFile(String fileName) {
		File file = new File(getConfigFolder(), fileName); // read file from configuration folder

		if(file.exists() && getProperty(PRODMOD, "DEV").equalsIgnoreCase("DEV")) {
			file.delete();
		}

		// Generate the needed file
		if(!file.exists()) {
			URL url = getClass().getResource(RESOURCES + fileName);
			try {
				final InputStream is = url.openStream();
				final FileOutputStream fos = new FileOutputStream(file);
				// Do copy file
				byte[] buffer = new byte[1024];
				int bytesRead;
				try {
					bytesRead = is.read(buffer);
					while (bytesRead >= 0) {
						fos.write(buffer, 0, bytesRead);
						bytesRead = is.read(buffer);
					}
				}catch (IOException e) {
					logger.error(e.getMessage(), e.getCause());
				}finally {
					try {
						is.close();
						fos.close();
					}catch (IOException e) {
						logger.error(e.getMessage(), e.getCause());
					}
				}
			}catch (IOException e) {
				logger.error(e.getMessage(), e.getCause());
			}
		}

		// Set the return result
		URL result = null;
		try {
			File f = new File(getConfigFolder(), fileName);
			result = f.toURI().toURL();
		}catch (MalformedURLException e) {
			logger.error(e.getMessage(), e.getCause());
		}

		return result;
	}

	public static File getConfigFolder() {
		File file = new File(CURRENTPATH, CONFIGF);
		if(!file.exists()) {
			file.mkdir();
		}

		return file;
	}

	public static File getConfigIni() {
		return (new File(getConfigFolder(), INIFILE));
	}

	public String getLastLocation() {
		return prop.getProperty(LAST_LOCATION);
	}

	public String getLastFileName() {
		return prop.getProperty(LAST_FILENAME);
	}

	public void storingPropertiesFile() throws IOException {
		FileOutputStream out = new FileOutputStream(this.propertyFile);
		if(getProperty(PRODMOD, "DEV").equalsIgnoreCase("DEV")) {
			setProperty(AppUtilities.PRODMOD, "DEV");
		}

		prop.store(out, HEADER);
		out.close();
	}

	public void setProperty(String key, String value) {
		getProp().setProperty(key, value);
	}

	public String getProperty(String key, String defaultValue) {
		return getProp().getProperty(key, defaultValue);
	}

	protected Properties getProp() {
		return prop;
	}

	public File getPropertyFile() {
		return propertyFile;
	}
}
